#include "pix5core.h"

Dict<String,FileSource*> IO::_mounts;
Mutex IO::_mtx;

void IO::init()
{
}

void IO::shutdown()
{
}

void IO::mount(const String& mountPoint,FileSource* fs)
{
	_mtx.lock();

		try
		{
			if(_mounts.hasKey(mountPoint))
				throw Error("Mount point already exists");

			_mounts.add(mountPoint,fs);

			try
			{
				fs->onMount(mountPoint);
			}
			catch(Error)
			{
				_mounts.remove(mountPoint);
				throw;
			}
		}
		catch(Error)
		{
			_mtx.unlock();
			throw;
		}

	_mtx.unlock();

}

void IO::unmount(const String& mountPoint)
{
	_mtx.lock();

		try
		{
			if(!_mounts.hasKey(mountPoint))
				throw Error("Mount point doesn't exists");

			FileSource* fs = _mounts[mountPoint];

			fs->onUnmount(mountPoint);
			
			_mounts.remove(mountPoint);
			delete fs;

		}
		catch(Error)
		{
			_mtx.unlock();
			throw;
		}

	_mtx.unlock();
}


File* IO::openFile(const String& path,bool write,bool create)
{
	File* f;

	_mtx.lock();

		try
		{
			String mountPoint = FilePath::getMountPoint(path);
			
			if(!_mounts.hasKey(mountPoint))
				throw Error("Mount point doesn't exists");

			f = _mounts[mountPoint]->openFile(FilePath::getPath(path,true),write,create);
		}
		catch(Error)
		{
			_mtx.unlock();
			throw;
		}

	_mtx.unlock();

	return f;
}

void IO::copyFile(const String& src,const String& dest)
{
	// Open the source file
	File* fsrc = IO::openFile(src);

	try
	{
		// Open the destination file
		File* fdest = IO::openFile(dest,true,true);

		try
		{
			// Copy the file, 64k at a time
			char buf[65536];

			long long size = fsrc->getSize();
			while(size)
			{
				// Get the block size
				int csize = size>65536 ? 65536 : (int)size;

				// Read and write
				fsrc->read(buf,csize);
				fdest->write(buf,csize);

				size -= csize;
			}
		}
		catch(Error)
		{
			delete fdest;
			throw;
		}
	
		delete fdest;
	}
	catch(Error)
	{
		delete fsrc;
		throw;
	}

	delete fsrc;
}



